Rearrange string k distance apart [Greedy, Heap]¶
Time: O(N); Space: O(N); hard
Given a non-empty string s and an integer k, rearrange the string such that the same characters are at least distance k from each other.
All input strings are given in lowercase letters. If it is not possible to rearrange the string, return an empty string “”.
Example 1:
Input: s = “aabbcc”, k = 3
Output: “abcabc”
Explanation:
The same letters are at least distance 3 from each other.
Example 2:
Input: s = “aaabc”, k = 3
Output: “”
Explanation:
It is not possible to rearrange the string.
Example 3:
Input: s = “aaadbbcc”, k = 2
Output: “abacabcd”
Explanation:
The same letters are at least distance 2 from each other.
1. Greedy [O(N), O(N)]¶
[11]:
class Solution1(object):
"""
Time: O(N)
Space: O(N)
"""
def rearrangeString(self, s, k):
"""
:type s: str
:type k: int
:rtype: str
"""
cnts = [0] * 26
for c in s:
cnts[ord(c) - ord('a')] += 1
sorted_cnts = []
for i in range(26):
sorted_cnts.append((cnts[i], chr(i + ord('a'))))
sorted_cnts.sort(reverse=True)
max_cnt = sorted_cnts[0][0]
blocks = [[] for _ in range(max_cnt)]
i = 0
for cnt in sorted_cnts:
for _ in range(cnt[0]):
blocks[i].append(cnt[1])
i = (i + 1) % max(cnt[0], max_cnt - 1)
for i in range(max_cnt-1):
if len(blocks[i]) < k:
return ''
return ''.join(map(lambda x : ''.join(x), blocks))
[12]:
sol = Solution1()
s = "aabbcc"
k = 3
# print(sol.rearrangeString(s, k))
assert sol.rearrangeString(s, k) == "abcabc" or "cbacba"
s = "aaabc"
k = 3
assert sol.rearrangeString(s, k) == ""
s = "aaadbbcc"
k = 2
# print(sol.rearrangeString(s, k))
assert sol.rearrangeString(s, k) == "abacabcd" or "acbdacba"
2. Heap¶
[15]:
from collections import Counter
from heapq import heappush, heappop
class Solution2(object):
def rearrangeString(self, s, k):
"""
:type str: str
:type k: int
:rtype: str
"""
if k <= 1:
return s
cnts = Counter(s)
heap = []
for c, cnt in cnts.items():
heappush(heap, [-cnt, c])
result = []
while heap:
used_cnt_chars = []
for _ in range(min(k, len(s) - len(result))):
if not heap:
return ''
cnt_char = heappop(heap)
result.append(cnt_char[1])
cnt_char[0] += 1
if cnt_char[0] < 0:
used_cnt_chars.append(cnt_char)
for cnt_char in used_cnt_chars:
heappush(heap, cnt_char)
return ''.join(result)
[16]:
sol = Solution2()
s = "aabbcc"
k = 3
# print(sol.rearrangeString(s, k))
assert sol.rearrangeString(s, k) == "abcabc" or "cbacba"
s = "aaabc"
k = 3
assert sol.rearrangeString(s, k) == ""
s = "aaadbbcc"
k = 2
# print(sol.rearrangeString(s, k))
assert sol.rearrangeString(s, k) == "abacabcd" or "acbdacba"